#ifndef __COMM_HPP__
#define __COMM_HPP__

#include <iostream>
#include <cerrno>
#include <cstring>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cassert>
#include <unistd.h>

using namespace std;

#define Mode 0666
#define Path "./fifo"

class Fifo {
public:
Fifo(const string &path=Path)
: _path(path)
{
    umask(0);
    //创建命名管道
    int ret = mkfifo(_path.c_str(), Mode);
    if (ret == 0) {
       cout<<"create fifo success"<<endl;
    } else {
       cout<<"create fifo failed"<<endl;
    }
    
}


~Fifo()
{
    //删除指定路径的文件或目录
    int ret = unlink(_path.c_str());
      if (ret == 0) {
       cout<<"delete fifo success"<<endl;
    } else {
       cout<<"delete fifo failed"<<endl;
    }
}

private:
    string _path;//文件路径+文件名
};


class Sync
{
   public:
   Sync()
   :rfd(-1)
   ,wfd(-1)
   {}

   void OpenReadOrDie()
   {
      rfd = open(Path, O_RDONLY);

      if(rfd == -1)
      {
          perror("open fifo failed");
          exit(1);
      }    
   }

   void OpenWriteOrDie()
   {
      wfd = open(Path, O_WRONLY);

      if(wfd == -1)
      {
          perror("open fifo failed");
          exit(1);
      }    
   }

/**
 * 等待服务器唤醒
 * 
 * 本函数通过读取文件描述符rfd来等待服务器的唤醒信号当接收到信号后会尝试从共享内存中读取数据
 * 如果服务器关闭或读取操作失败，函数将返回false，表示等待失败
 * 
 * @return bool 表示等待结果true表示成功接收到服务器唤醒信号并完成读取操作，false表示等待或读取失败
 */
bool Wait()
{
    // 初始化返回值为true，表示等待成功
    bool ret = true;

    // 定义一个32位无符号整型变量c用于接收从文件描述符读取的数据
    uint32_t c=0;

    // 尝试从文件描述符rfd读取数据到变量c中，读取大小为c的大小
    ssize_t n=read(rfd, &c, sizeof(c));

    // 如果读取到的数据大小与预期相符，表示成功接收到服务器唤醒信号
    if (n==sizeof(c))
    {
        cout<<"server wakeup,begin read shm...."<<endl;
    }
    // 如果读取到的数据大小为0，可能表示服务器已关闭
    else if (n==0)
    {
        cout<<"server close,exit...."<<endl;
        // 设置返回值为false，表示等待失败
        ret = false;
    }
    // 如果读取操作失败
    else
    {
        // 返回false，表示等待失败
        return false;
    }

    // 返回等待结果
    return ret;
}

/**
 * @brief 唤醒服务器开始工作
 * 
 * 本函数通过写入一个文件描述符wfd来唤醒服务器。它首先定义一个32位无符号整数c并初始化为0，
 * 然后尝试将c的值写入wfd指向的文件或设备。如果写入操作成功完成（即写入的字节数等于c的大小），
 * 则打印一条消息表示服务器已被唤醒并准备开始读取共享内存。如果写入操作失败（即写入的字节数不等于c的大小），
 * 则打印一条消息表示服务器唤醒失败。
 */
void Wakeup()
{
    // 初始化一个32位无符号整数为0，用于唤醒信号
    uint32_t c=0;
    // 尝试将c的值写入文件描述符wfd指向的文件或设备
    ssize_t n=write(wfd, &c, sizeof(c));

    // 根据写入结果判断服务器是否成功唤醒
    if (n==sizeof(c))
    {
        // 如果写入成功，打印唤醒成功的消息
        cout<<"server wakeup,begin read shm...."<<endl;
    }
    else
    {
        // 如果写入失败，打印唤醒失败的消息
        cout<<"server wakeup failed"<<endl;
    }
}

~Sync()
{
  
}

   private:

   int rfd;
   int wfd;  
};

#endif

